home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / HAM_RAD / 3176.ZIP / ICOM1.ZIP / IBMIC232.PGM < prev    next >
Text File  |  1986-08-23  |  9KB  |  433 lines

  1.  
  2. Here's the source code I wrote for controlling the ICOM radios through my PC
  3. clone's printer port. Note that all frequencies are represented in hertz,
  4. using longs; this makes things more consistent since different radio functions
  5. require different precision.
  6.  
  7. -----------
  8. /* icom.c
  9.  * Library functions for driving the ICOM computer interface
  10.  * Copyright 1986 by Phil Karn, KA9Q
  11.  * Permission granted for free noncommercial copying and use by
  12.  * licensed radio amateurs.
  13.  */
  14. #include "icom.h"
  15.  
  16. char *modes[] = {
  17. "LSB",    /* 0 */
  18. "USB",    /* 1 */
  19. "AM",    /* 2 */
  20. "CW",    /* 3 */
  21. "RTTY",    /* 4 */
  22. "FM",    /* 5 */
  23. "CW Narrow",    /* 6 */
  24. "RTTY Narrow",    /* 7 */
  25. "lsb",    /* 8 */
  26. "usb",    /* 9 */
  27. "am",    /* a */
  28. "cw narrow",    /* b */
  29. "rtty narrow",    /* c */
  30. "fm",    /* d */
  31. "0xe",    /* e */
  32. "0xf"    /* f */
  33. };
  34.  
  35. /* Read band */
  36. int
  37. read_band(freq,lower,upper)
  38. long freq;        /* Used just to select the radio */
  39. long *lower,*upper;    /* Band limits returned through here */
  40. {
  41.     register int i;
  42.  
  43.     start_cmd();
  44.     if(send_byte(BAND | band(freq)) < 0){
  45.         end_cmd();
  46.         return -1;
  47.     }
  48.     *upper = 0;
  49.     read_byte();        /* Toss opening delim */
  50.     for(i=0;i<6;i++)
  51.         *upper = *upper * 10 + (read_byte() & 0xf);
  52.     read_byte();        /* Toss closing delim */
  53.     *upper *= 10000;    /* Convert to hertz */
  54.  
  55.     *lower = 0;
  56.     read_byte();        /* Toss second opening delim */
  57.     for(i=0;i<6;i++)
  58.         *lower = *lower * 10 + (read_byte() & 0xf);
  59.     read_byte();        /* Toss second closing delim */
  60.     *lower *= 10000;    /* Convert to hertz */    
  61.     end_cmd();
  62.     return 0;
  63. }
  64. /* Set frequency; the proper radio is automatically selected */
  65. int
  66. set_freq(freq)
  67. long freq;    /* Frequency, hertz */
  68. {
  69.     register int i;
  70.     char fstr[15];
  71.  
  72.     start_cmd();
  73.     if(send_byte(FREQ | band(freq)) < 0){
  74.         end_cmd();
  75.         return -1;
  76.     }
  77.     send_byte(FREQ | 0xd);
  78.     sprintf(fstr,"%09ld",freq/10);
  79.     for(i=0;i<9;i++)
  80.         send_byte(FREQ | (fstr[i] - '0'));
  81.     send_byte(FREQ | 0xe);
  82.     end_cmd();
  83.     return 0;
  84. }
  85.  
  86. /* Read frequency */
  87. long
  88. read_freq(freq)
  89. long freq;    /* For band selection only */
  90. {
  91.     register int i;
  92.  
  93.     start_cmd();
  94.     if(send_byte(FREQ | band(freq)) < 0){
  95.         end_cmd();
  96.         return -1;
  97.     }
  98.     if(read_byte() < 0)     /* Discard opening delimiter */
  99.         return -1;
  100.     freq = 0;
  101.     for(i=0;i<9;i++){
  102.         freq = freq * 10 + (read_byte() & 0xf);
  103.     }
  104.     read_byte();        /* Discard closing delimiter */
  105.     freq *= 10;
  106.     end_cmd();
  107.     return freq;
  108. }
  109. /* set mode */
  110. int
  111. set_mode(freq,mode)
  112. long freq;        /* For radio selection */
  113. int mode;        /* Desired operating mode */
  114. {
  115.     start_cmd();
  116.     if(send_byte(MODE | band(freq)) < 0){
  117.         end_cmd();
  118.         return -1;
  119.     }
  120.     send_byte(MODE | 0xd);
  121.     send_byte(MODE | mode);
  122.     send_byte(MODE | 0xe);
  123.     end_cmd();
  124.     return 0;
  125. }
  126. /* Return current mode */
  127. int
  128. read_mode(freq)
  129. long freq;        /* For radio selection */
  130. {
  131.     int c;
  132.  
  133.     start_cmd();
  134.     if(send_byte(MODE | band(freq)) < 0){
  135.         end_cmd();
  136.         return -1;
  137.     }
  138.     read_byte();
  139.     c = read_byte();
  140.     read_byte();
  141.     end_cmd();
  142.     return c & 0xf;
  143. }
  144. /* Set offset */
  145. int
  146. set_offset(freq,offset)
  147. long freq;    /* For radio selection */
  148. long offset;    /* Offset, hertz */
  149. {
  150.     register int i;
  151.     char fstr[15];
  152.  
  153.     start_cmd();
  154.     if(send_byte(OFFSET | band(freq)) < 0){
  155.         end_cmd();
  156.         return -1;
  157.     }
  158.     send_byte(OFFSET | 0xd);
  159.     sprintf(fstr,"%09ld",freq/1000);
  160.     for(i=0;i<9;i++)
  161.         send_byte(OFFSET | (fstr[i] - '0'));
  162.     send_byte(OFFSET | 0xe);
  163.     end_cmd();
  164.     return 0;
  165. }
  166.  
  167. /* Read offset */
  168. long
  169. read_offset(freq)
  170. long freq;    /* For radio selection */
  171. {
  172.     register int i;
  173.     long offset;
  174.     
  175.     start_cmd();
  176.     if(send_byte(OFFSET | band(freq)) < 0){
  177.         end_cmd();
  178.         return -1;
  179.     }
  180.     read_byte();     /* Discard opening delimiter */
  181.     offset = 0;
  182.     for(i=0;i<9;i++)
  183.         offset = offset * 10 + (read_byte() & 0xf);
  184.     read_byte();    /* Discard closing delimiter */
  185.     offset *= 1000;
  186.     end_cmd();
  187.     return offset;
  188. }
  189. /* Select memory channel or vfo */
  190. int
  191. set_mem(freq,val)
  192. long freq;        /* For radio selection */
  193. int val;        /* Desired VFO/channel number */
  194. {
  195.     start_cmd();
  196.     if(send_byte(MEMVFO | band(freq)) < 0){
  197.         end_cmd();
  198.         return -1;
  199.     }
  200.     send_byte(MEMVFO | 0xd);
  201.     send_byte(MEMVFO | ((val >> 4) & 0xf));    /* tens digit */
  202.     send_byte(MEMVFO | (val & 0xf));    /* units digit */
  203.     send_byte(MEMVFO | 0xe);
  204.     end_cmd();
  205.     return 0;
  206. }
  207. /* Transfer between VFO and memory */
  208. int
  209. transfer(freq,dir)
  210. long freq;        /* For radio selection */
  211. int dir;        /* Desired direction of transfer */
  212. {
  213.     start_cmd();
  214.     if(send_byte(MEMRW | band(freq)) < 0){
  215.         end_cmd();
  216.         return -1;
  217.     }
  218.     send_byte(MEMRW | 0xd);
  219.     send_byte(MEMRW | dir);
  220.     send_byte(MEMRW | 0xe);
  221.     end_cmd();
  222.     return 0;
  223. }
  224. /* Set band
  225.  * Uses the hack by NG6Q in April 1986 Ham Radio
  226.  * Warning: untested (I don't have a 751).
  227.  */
  228. int
  229. set_band(freq,b)
  230. long freq;        /* For radio selection */
  231. int b;            /* Desired band */
  232. {
  233.     long funny;
  234.  
  235.     set_mem(freq,38);    /* Select channel 38 */
  236.     funny = (freq/1000000) * 1000000;    /* Truncate to Mhz */
  237.     funny += 100000 * b;        /* Desired band goes in 100khz digit*/
  238.     set_freq(funny);
  239.     transfer(freq,WRITE);        /* Store in memory */
  240.     set_mem(freq,0);        /* Go back to VFO */
  241.     transfer(freq,READ);        /* Get the funny value */
  242.     set_freq(freq);            /* Put in the one we really want */
  243.     return 0;
  244. }
  245.  
  246. /* The following are internal subroutines that perform the low-level
  247.  * parts of the host/radio protocol. These can be "static" if you wish.
  248.  */
  249.  
  250. /* Send individual byte of a message */
  251. int
  252. send_byte(c)
  253. char c;
  254. {    
  255.     register int i;
  256.  
  257.     outportb(I_DATA,c);
  258.  
  259.     /* Turn on WP and output mode in addition to SRQ */
  260.     outportb(I_CTL,CTL_POL^(SRQ_CMD|WP_CMD|OUTPUT_MODE));
  261.  
  262.     /* Wait for DAV to go active low */
  263.     for(i=TIMEOUT;i != 0;i--){
  264.         if((inportb(I_DAV) & DAV_STAT) == 0)
  265.             break;
  266.     }
  267.     if(i == 0){
  268.         outportb(I_CTL,CTL_POL);
  269.         printf("sendbyte fail\n");
  270.         return -1;
  271.     }
  272.     /* Drop WP and output mode, keeping SRQ active */
  273.     outportb(I_CTL,CTL_POL^SRQ_CMD);
  274.  
  275.     /* Wait for DAV to go inactive high */
  276.     for(i=TIMEOUT;i != 0;i--){
  277.         if((inportb(I_DAV) & DAV_STAT) != 0)
  278.             break;
  279.     }        
  280.     if(i == 0){
  281.         outportb(I_CTL,CTL_POL);
  282.         printf("sendbyte fail 2\n");
  283.         return -2;
  284.     }
  285.     return 0;
  286. }
  287.  
  288. /* Read individual byte within a message */
  289. int
  290. read_byte()
  291. {
  292.     register int i;
  293.     register int c;
  294.  
  295.     /* Configure for input */
  296.     outportb(I_CTL,CTL_POL^(RP_CMD|SRQ_CMD));
  297.  
  298.     /* Wait for DAV to go active low */
  299.     for(i=TIMEOUT;i != 0;i--){
  300.         if((inportb(I_DAV) & DAV_STAT) == 0)
  301.             break;
  302.     }
  303.     if(i == 0){
  304.         outportb(I_CTL,CTL_POL);
  305.         printf("read fail\n");
  306.         return -1;
  307.     }
  308.     /* Read data byte from bus */
  309.     c = inportb(I_DATA);
  310.  
  311.     /* Drop RP, keeping SRQ active */
  312.     outportb(I_CTL,CTL_POL^SRQ_CMD);
  313.  
  314.     /* Wait for DAV to go inactive high */
  315.     for(i=TIMEOUT;i != 0;i--){
  316.         if((inportb(I_DAV) & DAV_STAT) != 0)
  317.             break;
  318.     }        
  319.     if(i == 0){
  320.         outportb(I_CTL,CTL_POL);
  321.         printf("read fail 2\n");
  322.         return -2;
  323.     }
  324.     return c & 0xff;
  325. }
  326. /* Derive band number from frequency */
  327. int
  328. band(freq)
  329. register long freq;
  330. {
  331.     if(freq >= 1200000000){
  332.         return MHZ_1200;
  333.     } else if(freq >= 420000000){
  334.         return MHZ_430;
  335.     } else if(freq >= 220000000){
  336.         return MHZ_220;
  337.     } else if(freq >= 140000000){
  338.         return MHZ_144;
  339.     } else if(freq >= 50000000){
  340.         return MHZ_50;
  341.     } else
  342.         return HF;
  343. }
  344. /* Begin a message */
  345. start_cmd()
  346. {
  347.     /* Assert SRQ */
  348.     outportb(I_CTL,CTL_POL^SRQ_CMD);
  349. }
  350. /* End a message */
  351. end_cmd()
  352. {
  353.     register int i;
  354.  
  355.     /* Wait a little bit */
  356.     for(i=WAIT;i != 0;i--)
  357.         ;
  358.     /* Deactivate SRQ */
  359.     outportb(I_CTL,CTL_POL);
  360. }
  361. -----------------
  362. /* icom.h
  363.  * Definitions for the ICOM library functions
  364.  * 21 Aug 1986
  365.  * Phil Karn, KA9Q
  366.  */
  367.  
  368. /* System-dependent constants; edit to taste */
  369.  
  370. /* Port addresses */
  371. #define    I_DATA        0x3bc    /* Data I/O port */
  372. #define    I_CTL        0x3be    /* Control port (output) */
  373. #define    I_DAV        0x3bd    /* Data available port (input) */
  374.  
  375. /* Bits within I_DAV */
  376. #define    DAV_STAT    0x40
  377. #define    DAV_POL        0x40    /* DAV is negative polarity */
  378.  
  379. /* Bits within I_CTL */
  380. #define    OUTPUT_MODE    0x20
  381. #define    RP_CMD        0x8
  382. #define    WP_CMD        0x2
  383. #define    SRQ_CMD        0x1
  384. /* Specify any bits in I_CTL which are negative logic.
  385.  * Output mode, RP and WP are negative logic; SRQ is positive
  386.  */
  387. #define    CTL_POL    (OUTPUT_MODE|RP_CMD|WP_CMD)
  388.  
  389. /* These two values were found experimentally to work on an 8-MHz 8088
  390.  * Increase WAIT if you get frequent timeouts or protocol lockups
  391.  */
  392. #define    TIMEOUT    65535    /* Timeout on a read/write operation */
  393. #define    WAIT    1100    /* Delay at end of sequence */
  394.  
  395. /* The following definitions are fixed by the ICOM design; they should not
  396.  * have to be changed.
  397.  */
  398.  
  399. /* Commands */
  400. #define    BAND        0x10
  401. #define    FREQ        0x20
  402. #define    MODE        0x30
  403. #define    OFFSET        0x40
  404. #define    MEMVFO        0x50
  405. #define    MEMRW        0x60
  406.  
  407. /* Addresses */
  408. #define    HF        0x1    /* IC-71 or IC-751 */
  409. #define    MHZ_50        0x2
  410. #define    MHZ_144        0x3    /* IC-271 */
  411. #define    MHZ_220        0x4
  412. #define    MHZ_430        0x5    /* IC-471 */
  413. #define    MHZ_1200    0x6    /* IC-1271 */
  414.  
  415. /* Modes */
  416. #define    LSB    0
  417. #define    USB    1
  418. #define    AM    2
  419. #define    CW    3
  420. #define    RTTY    4
  421. #define    FM    5
  422. #define    CWN    6
  423. #define    RTTYN    7
  424.  
  425. #define    WRITE    1    /* VFO to memory */
  426. #define    READ    2    /* Memory to VFO */
  427.  
  428. long read_freq();
  429. --------------
  430. End of code
  431.  
  432.  
  433.